package Compile.CIFA;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

public class cifa {
    /*
    * 存储待分析的SQL语句
    * */
    private String input;
    /*
    * 记录当前分析到的字符的下标
    * */
    private int index;

    /*
    * 记录当前词法分析是否出错
    * true: 合法
    * false: 不合法
    * */
    public boolean flag = true;

    /*
    * 定义 KEYWORDS 列表
    * 用于存储SQL语言中的关键字，识别和分类单词
    * */
    private static final List<String> KEYWORDS = Arrays.asList(
            "create", "table", "insert", "into", "values", "update", "set",
            "select", "from", "where", "order", "by", "asc", "desc", "show",
            "tables", "desc", "drop", "help", "quit", "delete");

    public cifa(String input) {
        this.input = input;
        this.index = 0;
    }

    /*
    * 读取输入的SQL语句，识别其中的单词并返回一个Token列表，结尾加上 #
    * Func: 分析SQL语句
    * Return: List<Token>
    * */
    public List<Token> analyze() throws Exception {
        // 存储词法分析结果
        List<Token> tokens = new ArrayList<>();
        if (input.length() == 1) {
            tokens.add(new Token(input, TokenType.ERROR_TYPE));
            return tokens;
        }
        // 逐字符读取SQL语句
        while (index < input.length() && flag) {
            char currentChar = input.charAt(index);
            // 滤掉空格、换行、制表符
            if (currentChar == ' ' || currentChar == '\n' || currentChar == '\t') {
                index++;
            }
            // 关键字、标识符处理
            else if (Character.isLetter(currentChar) || currentChar == '_') {
                tokens.add(getIdentifier());
            }
            // 数字处理
            else if (Character.isDigit(currentChar) || currentChar == '.' || (currentChar == '-' && (Character.isDigit(input.charAt(index+1)) || input.charAt(index+1) == '.'))) {
                tokens.add(getNumber());
            }
            // 字符串处理
            else if (currentChar == '\'') {
                tokens.add(getString());
            }
            // 分隔符处理
            else if (currentChar == '(' || currentChar == ')' || currentChar == ',' || currentChar == ';') {
                tokens.add(new Token(String.valueOf(currentChar), TokenType.SEPARATOR));
                index++;
            }
            // 注释处理
            // 单行注释
            else if (currentChar == '-' && input.charAt(index+1) == '-') {
                /*
                * 单行注释格式为
                * -- 这里是注释
                * 是则词法分析结束，直接返回tokens
                * */
                tokens.add(new Token(input.substring(2), TokenType.ANNOTATION));
                tokens.add(new Token("#", TokenType.JINGHAO));
                return tokens;
            }
            // 操作符处理
            else if (currentChar == '=' || currentChar == '>' || currentChar == '<') {
                if (currentChar == '=') {
                    tokens.add(new Token("=", TokenType.OPERATOR));
                    index++;
                }
                else if (currentChar == '<' && input.charAt(index+1) == '=') {
                    tokens.add(new Token("<=" , TokenType.OPERATOR));
                    index += 2;
                } else if (currentChar == '>' && input.charAt(index+1) == '=') {
                    tokens.add(new Token(">=" , TokenType.OPERATOR));
                    index += 2;
                } else if (currentChar == '<' && input.charAt(index+1) == '>') {
                    tokens.add(new Token("<>" , TokenType.OPERATOR));
                    index += 2;
                } else if (currentChar == '<') {
                    tokens.add(new Token("<" , TokenType.OPERATOR));
                    index++;
                } else {
                    tokens.add(new Token(">" , TokenType.OPERATOR));
                    index++;
                }
            } else if (currentChar == '*') {
                tokens.add(new Token("*", TokenType.KEYWORD));
                index++;
            }
            // 非法字符
            else {
                // 记录出错字符，返回Tokens
                tokens.add(new Token(String.valueOf(currentChar), TokenType.ERROR_TYPE));
                flag = false;
                return tokens;
            }
        }
        if(flag) tokens.add(new Token("#", TokenType.JINGHAO));
        return tokens;
    }

    /*
    * INT
    * FLOAT
    * */
    private Token getNumber() {
        int start = index;
        // 记录是否为浮点数
        boolean isFloat = input.charAt(index) == '.';
        boolean isNegative = input.charAt(index) == '-';
        if (isNegative) index++;
        while (index < input.length() && (Character.isDigit(input.charAt(index)) || input.charAt(index) == '.')) {
            if (input.charAt(index) != '.') {
                index++;
            } else if (start == index) {
                index++;
            } else if (!isFloat) {
//                System.out.println(input.charAt(index) + "小数点第一次出现");
                isFloat = true;
                index++;
            } else {
                // 小数点第2次出现 ERROR
//                System.out.println(input.charAt(index) + "小数点第二次出现");
                flag = false;
                return new Token(input.substring(start, index+1), TokenType.ERROR_TYPE);
            }
        }
        if (!isFloat) return new Token(input.substring(start, index), TokenType.INTV);
        return new Token(input.substring(start, index), TokenType.FLOATV);
    }

    /*
    * String
    * */
    private Token getString() throws Exception {
        int start = index;
        index++;
        while (index < input.length()) {
            if (input.charAt(index) == '\'') {
                index++;
                return new Token(input.substring(start, index), TokenType.STRINGV);
            } else {
                index++;
            }
        }
        flag = false;
        return new Token(input.substring(start, index), TokenType.ERROR_TYPE);
    }

    /*
    * 识别关键字、标识符
    * Return: Token<Value, Type>
    * */
    private Token getIdentifier() {
        // 提取字符串(TokenValue)
        int start = index;
        while (index < input.length() &&
                (Character.isLetterOrDigit(input.charAt(index)) || input.charAt(index) == '_')) {
            index++;
        }
        String identifier = input.substring(start, index).toLowerCase();
        // 提取TokenType
        TokenType tokenType;
        if (KEYWORDS.contains(identifier.toLowerCase())) {
            tokenType = TokenType.KEYWORD;
        } else if (identifier.equalsIgnoreCase("INT")) {
            tokenType = TokenType.INT;
        } else if (identifier.equalsIgnoreCase("FLOAT")) {
            tokenType = TokenType.FLOAT;
        } else if (identifier.equalsIgnoreCase("STRING")) {
            tokenType = TokenType.STRING;
        } else {
            tokenType = TokenType.IDENTIFIER;
        }
        return new Token(identifier, tokenType);
    }

}
